package edu.ccut.saturn.studio.wfg.model;

import org.eclipse.draw2d.Graphics;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Display;

import edu.ccut.saturn.studio.logic.model.BasicShape;
import edu.ccut.saturn.studio.wfg.dialog.routerdialog.SaturnRouterConnectionDialog;
import edu.ccut.saturn.studio.wfg.wfgmodel.SaturnEndNode;
import edu.ccut.saturn.studio.wfg.wfgmodel.SaturnInformationNode;
import edu.ccut.saturn.studio.wfg.wfgmodel.SaturnRouter;
import edu.ccut.saturn.studio.wfg.wfgmodel.SaturnRouterNode;
import edu.ccut.saturn.studio.wfg.wfgmodel.SaturnStartNode;

public class Connection extends BasicShape {

	private static final long serialVersionUID = 1129718762625130932L;

	public static final Integer SOLID_CONNECTION = Graphics.LINE_SOLID;

	public static final String LINESTYLE_PROP = "LineStyle";
	
	public static final String LINE_NAME_PROPERTY = "line_name_property";
	
	private boolean isConnected;

	private int lineStyle = Graphics.LINE_SOLID;

	public static final Integer EXCEPTION_CONNECTION = Graphics.LINE_CUSTOM;

	private Shape source;

	private Shape target;
	
	private String lineName = "";
	
	private String exprTemp = "";
	
	private String lineNameTemp = "";
	
	public String getExprTemp() {
		return exprTemp;
	}

	public void setExprTemp(String exprTemp) {
		this.exprTemp = exprTemp;
	}

	public String getLineNameTemp() {
		return lineNameTemp;
	}

	public void setLineNameTemp(String lineNameTemp) {
		this.lineNameTemp = lineNameTemp;
	}

	public String getLineName() {
		return lineName;
	}

	public void setLineName(String lineName) {
		this.lineName = lineName;
		firePropertyChange(LINE_NAME_PROPERTY, null, lineName);
	}

	public Connection(Shape source, Shape target, int lineStyle) {
		this.lineStyle = lineStyle;
		reconnect(source, target);
	}
	
	public Connection(Shape source, Shape target, int lineStyle,String type) {
		this.lineStyle = lineStyle;
		reconnect(source, target,type);
	}

	public boolean isConnected() {
		return this.isConnected;
	}

	public void setConnected(boolean isConnected) {
		this.isConnected = isConnected;
	}

	public void disconnect() {
		if (this.isConnected) {
			if(this.source instanceof SaturnRouterNode){
				SaturnRouterNode saturnRouterNode = (SaturnRouterNode)this.source;
				saturnRouterNode.disSaturnRouter(this.target);
			}
			
			this.source.removeConnection(this);
			this.target.removeConnection(this);
			this.isConnected = false;
		}
	}

	public int getLineStyle() {
		return lineStyle;
	}

	public Shape getSource() {
		return source;
	}

	public Shape getTarget() {
		return target;
	}

	public void reconnect() {
		
		if(this.source instanceof SaturnRouterNode){
			SaturnRouterNode saturnRouterNode = (SaturnRouterNode)this.source;
			
			// SaturnRouterNode连接SaturnInformationNode不产生XML
			if(!(this.target instanceof SaturnInformationNode)){
				saturnRouterNode.setSaturnRouter(this.target, getExprTemp(), getLineNameTemp());
			}
		}
		
		if (!isConnected) {
			
			/**
			 * 每一种连线只能使用一次，SaturnRouter除外
			 */
			if (!(source instanceof SaturnRouterNode)) {
				if (source.getSourceConnections().size() != 0) {
					for (int i = 0; i < this.source.getSourceConnections().size(); i++) {
						if (source.getSourceConnections().get(i).getLineStyle() == 1) {
							return;
						}
					}
				}
			}
			
			/**
			 * 禁止自己连接自己
			 */
			if (source.equals(target)) {
				throw new IllegalArgumentException();
			}
			
			/**
			 * 描述信息不能被连接和连接别人
			 */
			if ((source instanceof SaturnInformationNode)
					|| (target instanceof SaturnInformationNode)) {
				this.source.setNextId("");
				return;
			}
			
			/**
			 * 开始节点不能被连接,结束节点不能连接出去
			 */
			if ((source instanceof SaturnEndNode)
					|| ((target instanceof SaturnStartNode) && (!(source instanceof SaturnRouterNode)))) {
				this.source.setNextId("");
				return;
			}
			
			/**
			 * 禁止反向连接
			 */
			if (target.getSourceConnections().size() != 0) {
				for (int i = 0; i < target.getSourceConnections().size(); i++) {
					if (target.getSourceConnections().get(i).getTarget().equals(source)) {
						this.source.setNextId("");
						return;
					}
				}
			}
			
			if(this.source instanceof SaturnRouterNode){
				this.source.setNextId("");
			} else {
				this.source.setNextId(this.target.getId().trim());
			}
			
			source.addConnection(this);
			target.addConnection(this);
			isConnected = true;
		}
	}
	
	public void reconnect(String type){
		if (!isConnected) {
			source.addConnection(this);
			target.addConnection(this);
			isConnected = true;
		}
	}

	public void reconnect(Shape newSource, Shape newTarget) {
		if (newSource == null || newTarget == null || newSource == newTarget) {
			throw new IllegalArgumentException();
		}
		coypTemp(this.source, this.target);
		disconnect();
		this.source = newSource;
		this.target = newTarget;
		reconnect();
	}
	
	public void reconnect(Shape newSource, Shape newTarget,String type) {
		if (newSource == null || newTarget == null || newSource == newTarget) {
			throw new IllegalArgumentException();
		}
		disconnect();
		this.source = newSource;
		this.target = newTarget;
		reconnect(type);
	}

	public void setLineStyle(int lineStyle) {
		if (lineStyle != Graphics.LINE_DASH && lineStyle != Graphics.LINE_SOLID) {
			throw new IllegalArgumentException();
		}
		this.lineStyle = lineStyle;
		firePropertyChange(LINESTYLE_PROP, null, new Integer(this.lineStyle));
	}
	
	/**
	 * 当移位一条连线时，如果源为SaturnRouterNode，给lineName赋值
	 * 
	 * */
	private void coypTemp(Shape source, Shape target){
		if(source instanceof SaturnRouterNode){
			for(SaturnRouter router: ((SaturnRouterNode)this.source).getRouterList()){
				if(this.target.getId().equals(router.getId())){
					
					setExprTemp(router.getKey());
					setLineNameTemp(router.getLineName());
				}
			}
		}
	}

	public Color getColor() {
		return new Color(null, 0, 0, 0);
	}
	
	// Connection也是一个模型，它也可以弹出对话框
	public Dialog getDialog(){
		SaturnRouterConnectionDialog dialog = new SaturnRouterConnectionDialog(Display.getDefault().getShells()[0],this);
		return dialog;
	}
}